// 将计算任务拆分成多个
package main

import (
	"log"
	"sync"
)

type task struct {
	begin  int
	end    int
	result chan<- int
}

func (t task) do() {
	sum := 0
	for i := t.begin; i <= t.end; i++ {
		sum += i
	}
	t.result <- sum
}

var sw = sync.WaitGroup{}

// 创建任务通道
// 划分计算范围
// 开始计算
// 统计计算结果
func main() {
	// 创建任务通道
	taskItems := make(chan task, 10)
	resultItems := make(chan int, 10)

	// 划分计算范围
	createTask(taskItems, resultItems, 100, 10)

	// 开始计算
	startDo(taskItems, resultItems)

	// 统计计算结果
	result := sumResult(resultItems)
	log.Println("计算结果：", result)
}

// 划分计算范围
func createTask(tasks chan<- task, r chan int, num int, interval int) {
	cishu := num / interval
	residueNum := num % interval
	// 处理可以整除的数据
	for i := 0; i < cishu; i++ {
		begin := interval*i + 1
		end := interval * (i + 1)
		t := task{
			begin:  begin,
			end:    end,
			result: r,
		}

		tasks <- t
	}

	// 分割剩余数量范围
	if residueNum != 0 {
		t := task{
			begin:  num*cishu + 1,
			end:    num,
			result: r,
		}

		tasks <- t
	}
	// 谁往里面插入数据就谁关闭
	defer close(tasks)
}

// 开始计算
// 把task取出来 然后开启goroutine
func startDo(tasks <-chan task, resultItems chan int) {
	for v := range   {
		sw.Add(1)
		go doNum(v)
	}

	sw.Wait()
	// 谁往里面插入数据就谁关闭
	defer close(resultItems)
}

// 实际计算
func doNum(tasks task) {
	tasks.do()
	defer sw.Done()
}

func sumResult(ch chan int) int {
	num := 0
	for v := range ch {
		num += v
	}
	return num
}
